package hermesV3.protocols;

import hermesV3.agent.AbstractProtocol;
import hermesV3.agent.Identifier;
import hermesV3.agent.Interaction;

/**
 * This Protocol manages the communication interactions during a whole iteration
 * of BioShape simulation. It permits to:
 * <ul>
 * <li>start a new iteration (sent by the {@code GlobalCoordinator};</li>
 * <li>end the current iteration (sent by each {@code LocalCoordinator} involved
 * in the simulation);</li>
 * <li>send the smallest step among FTS, FTC and delays (sent by each
 * {@code LocalCoordinator} involved in the simulation);</li>
 * <li>send the smallest step among all the involved {@code LocalCoordinator}
 * (sent by each {@code GlobalCoordinator};</li>
 * <li>send the spatial arrangement of simulation {@code Entity} objects for
 * visualisation purposes (sent by each {@code LocalCoordinator} involved in the
 * simulation).</li>
 * </ul>
 * 
 * @see it.unicam.cs.cosy.bioshape.core.components.GlobalCoordinator
 * @see it.unicam.cs.cosy.bioshape.core.components.LocalCoordinator
 * 
 * @author Federico Buti, Gaston Alanis, Matteo Micheletti, Andrea Piermarteri
 */
public class StepProtocol extends AbstractProtocol {

	/** Auto-generated serial ID */
	private static final long serialVersionUID = 5338161764057772696L;
	/** {@code Interaction} to start the iteration. */
	public static final String INTERACTIONSTART = "StartIteration";
	/** {@code Interaction} to end the iteration. */
	public static final String INTERACTIONEND = "EndIteration";
	/**
	 * {@code Interaction} to send to the {@code LocalCoordinator} the iteration
	 * step.
	 */
	public static final String INTERACTIONSENDSTEP = "SendStep";
	/**
	 * {@code Interaction} containing the current spatial arrangement. Sent to
	 * the {@code GlobalCoordinator} for visualisation purposes.
	 */
	public static final String INTERACTIONSENDSTATUS = "SendStatus";
	/**
	 * {@code Interaction} to send the smallest iteration step for the current
	 * iteration. sent by the {@code GlobalCoordinator}.
	 */
	public static final String INTERACTIONACKSTEP = "AckStep";
	/** {@code Interaction} to signal errors. */
	public static final String INTERACTIONERROR = "Error";

	/** Declares {@code Interaction}s among {@link StepProtocol} actions. */
	public StepProtocol() {
		super("StepProtocol");

		String[] parameterNameStartIteration = new String[1];
		parameterNameStartIteration[0] = "Delta";
		Class<?>[] parameterTypeStartIteration = new Class[1];
		parameterTypeStartIteration[0] = Double.class;
		Interaction startIteration = new Interaction(INTERACTIONSTART,
				INTERACTIONSTART, INTERACTIONSTART,
				parameterNameStartIteration, parameterTypeStartIteration);
		addInteraction(startIteration);

		String[] parameterNameEndIteration = new String[1];
		parameterNameEndIteration[0] = "Log";
		Class<?>[] parameterTypeEndIteration = new Class[1];
		parameterTypeEndIteration[0] = Object.class;
		Interaction EndIteration = new Interaction(INTERACTIONEND,
				INTERACTIONEND, INTERACTIONEND, parameterNameEndIteration,
				parameterTypeEndIteration);
		addInteraction(EndIteration);

		String[] parameterNameSendStep = new String[1];
		parameterNameSendStep[0] = "Step";
		Class<?>[] parameterTypeSendStep = new Class[1];
		parameterTypeSendStep[0] = Double.class;
		Interaction sendStep = new Interaction(INTERACTIONSENDSTEP,
				INTERACTIONSENDSTEP, INTERACTIONSENDSTEP,
				parameterNameSendStep, parameterTypeSendStep);
		addInteraction(sendStep);

		String[] parameterNameSendPairs = new String[1];
		parameterNameSendPairs[0] = "SendStatus";
		Class<?>[] parameterTypeSendPairs = new Class[1];
		parameterTypeSendPairs[0] = Object.class;
		Interaction sendPairs = new Interaction(INTERACTIONSENDSTATUS,
				INTERACTIONSENDSTATUS, INTERACTIONSENDSTATUS,
				parameterNameSendPairs, parameterTypeSendPairs);
		addInteraction(sendPairs);

		String[] parameterNameAckStep = new String[2];
		parameterNameAckStep[0] = "Step";
		parameterNameAckStep[1] = "id";
		Class<?>[] parameterTypeAckStep = new Class[2];
		parameterTypeAckStep[0] = Double.class;
		parameterTypeAckStep[1] = Identifier.class;
		Interaction ackStep = new Interaction(INTERACTIONACKSTEP,
				INTERACTIONACKSTEP, INTERACTIONACKSTEP, parameterNameAckStep,
				parameterTypeAckStep);
		addInteraction(ackStep);
		addResponseLink(sendStep, ackStep);

		String[] parameterNameError = new String[1];
		parameterNameError[0] = "Error";
		Class<?>[] parameterTypeError = new Class[1];
		parameterTypeError[0] = String.class;
		Interaction error = new Interaction(INTERACTIONERROR, INTERACTIONERROR,
				INTERACTIONERROR, parameterNameError, parameterTypeError);
		addInteraction(error);

		addErrorLink(startIteration, error);
		addErrorLink(sendStep, error);
		addErrorLink(sendPairs, error);
		addErrorLink(ackStep, error);
	}
}